#pragma once
#include "CDependencyObject.h"
#include "IWeakRefListener.h"
#include "REQUEST.h"


class CRenderTarget;
class CRepeatBehavior;
class CTimeSpan;
class CDuration;



class COptionalFloat;

class CTimeline :
	public CDependencyObject,
	public IWeakRefListener

{

protected: 
	CTimeline(CCoreServices * pCore);
protected: 
	virtual ~CTimeline();
public: 
	static HRESULT Create(CDependencyObject * * ppObject, CREATEPARAMETERS * pCreate);
	virtual HRESULT InitInstance();
	virtual HRESULT SetValue(CDependencyProperty * pdp, CValue * pValue);
	virtual XUINT32 GetTypeIndex() const;
	virtual HRESULT AddEventListener(CDependencyProperty * pdp, CValue * pValue, XINT32 iListenerType, CValue * pResult, XINT32 fHandledEventsToo);
	virtual HRESULT RemoveEventListener(CDependencyProperty * pdp, CValue * pValue);
	virtual HRESULT SetTemplatedParent(CDependencyObject * pDO);
	virtual HRESULT CloneForTarget(CRenderTarget * pRenderTarget, CTimeline * * ppTimeline);
	virtual XBOOL IsFiringEvents();
	virtual HRESULT OnManagedPeerCreated(XBOOL fIsCustomDOType, XBOOL fIsGCRoot);
	HRESULT ComputeState(const XFLOAT * pParentTime, XBOOL isParentInReverse, XFLOAT parentCombinedSpeedRatio, struct IFrameScheduler * pFrameScheduler, XBOOL * pHasNoExternalReferences);
	virtual HRESULT UpdateAnimation(XFLOAT beginTime, const XFLOAT * pParentTime, XBOOL isParentInReverse, XFLOAT combinedSpeedRatio, enum DurationType durationType, XFLOAT durationValue, XBOOL isInReverse, const COptionalFloat & expirationTime, struct IFrameScheduler * pFrameScheduler, XBOOL * pIsIndependentAnimation);
	virtual void GetNaturalDuration(enum DurationType * pDurationType, XFLOAT * prDurationValue);
	virtual HRESULT InitializeIteration(enum ClockState clockStatePrevious);
	virtual HRESULT FinalizeIteration(enum FillBehavior parentFillBehavior);
	virtual void EnsureIndependentStartDelta(XFLOAT independentStartTime);
	virtual HRESULT OnAddToTimeManager();
	virtual HRESULT OnRemoveFromTimeManager();
	virtual HRESULT OnBegin();
	void SetDynamicTimelineParent(CTimeline * pGeneratingParent);
	void SetTimingParent(CTimeline * pParent);
	CTimeline * GetTimingParent() const;
	CTimeline * GetRootTimingParent();
	HRESULT CheckCanBeModified();
	HRESULT SetTargetObject(CDependencyObject * pTarget);
	void SetTargetPropertyIndex(XUINT32 nPropertyIndex);
	CDependencyObject * GetTargetObject();
	XUINT32 GetTargetPropertyIndex();
	virtual XBOOL IsInActiveState();
	virtual XBOOL IsInStoppedState();
	XBOOL IsCompletedEventFired();
	virtual XBOOL IsAnimation();
	XBOOL HasIndependentAnimation();
protected: 
	virtual HRESULT ComputeStateImpl(const XFLOAT * pParentTime, XBOOL isParentInReverse, XFLOAT combinedSpeedRatio, struct IFrameScheduler * pFrameScheduler, XBOOL * pHasNoExternalReferences, XBOOL * pHasIndependentAnimation, XBOOL * pIsInReverse);
	HRESULT RequestTickToActivePeriodBegin(XFLOAT beginTime, const XFLOAT * pParentTime, XBOOL isParentInReverse, XFLOAT combinedSpeedRatio, struct IFrameScheduler * pFrameScheduler) const;
	HRESULT RequestTickToActivePeriodEnd(const XFLOAT * pParentTime, XBOOL isParentInReverse, XFLOAT combinedSpeedRatio, const COptionalFloat & expirationTime, struct IFrameScheduler * pFrameScheduler) const;
	virtual HRESULT CopyTimelineProperties(CRenderTarget * pRenderTarget, CTimeline * pTimeline);
	void FireCompletedEvent();
	virtual HRESULT ResolveLocalTarget(CCoreServices * pCoreServices, CTimeline * pParentTimeline);
	HRESULT CheckHasNoExternalRefs(XBOOL * pbHasNoExternalReferences);
	CWeakRef * GetTargetObjectWeakRef();
	XUINT32 GetTargetDependencyPropertyIndex();
	HRESULT ReleaseTarget();
	void ComputeExpirationTime(XFLOAT rBeginTime, enum DurationType durationType, XFLOAT rDurationValue, XFLOAT rAppliedSpeedRatio, COptionalFloat * poptExpirationTime);
	virtual HRESULT NotifyDestruction();
private: 
	CWeakRef * GetWeakRef(CDependencyObject * pObject);
	void ComputeEffectiveDuration(enum DurationType durationType, XFLOAT rDurationValue, XFLOAT rAppliedSpeedRatio, COptionalFloat * poptEffectiveDuration);
	void ComputeCurrentClockState(XFLOAT rBeginTime, COptionalFloat * poptExpirationTime, XFLOAT * pParentTime, XBOOL * pShouldComputeProgress);
	void ComputeLocalProgressAndTime(XFLOAT rBeginTime, XFLOAT rParentTime, enum DurationType durationType, XFLOAT rDurationValue, COptionalFloat * poptExpirationTime, XBOOL * pIsInReverseSegment);
public: 
	CXcpList<REQUEST> * m_pEventList;
	XFLOAT m_rSpeedRatio;
	CRepeatBehavior * m_pRepeatBehavior;
	enum FillBehavior m_fillBehavior;
	XBOOL m_fAutoReverse;
	static XBOOL s_allowDependentAnimations;
	CTimeSpan * m_pBeginTime;
	CDuration * m_pDuration;
	CString * m_pTargetName;
	CString * m_pTargetProperty;
	enum ClockState m_clockState;
	XFLOAT m_rCurrentTime;
protected: 
	XFLOAT m_rCurrentProgress;
	XUINT32 m_nIteration:29;
	XBOOL m_fInitialized:1;
	XBOOL m_fIsInTimeManager:1;
	XBOOL m_IsCompletedEventFired:1;
	CTimeline * m_pTimingParent;
	CWeakRef * m_pManualTargetObjectWeakRef;
	XUINT32 m_nManualTargetDependencyPropertyIndex;
	CWeakRef * m_pTargetObjectWeakRef;
	XUINT32 m_nTargetDependencyPropertyIndex;
private: 
	XBOOL m_fReleaseManagedPeer:1;
	XBOOL m_targetCallbackRegistered:1;
	XBOOL m_hasIndependentAnimation:1;
	void * m_hTemplatedParent;
	CTimeline * m_pDynamicTimelineParent;
	XUINT32 m_completedHandlerRegisteredCount;
};


